#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
调度系统API接口测试套件

本测试套件包含了调度系统所有API接口的测试用例，包括：
- 认证模块测试
- 用户管理测试
- 组织管理测试
- 人员管理测试
- 车辆管理测试
- 物料管理测试
- 工单管理测试

使用方法：
1. 确保后端服务已启动
2. 修改BASE_URL为实际的API地址
3. 运行测试：python api_test_suite.py
"""

import requests
import json
import time
from datetime import datetime
from typing import Dict, Any, Optional

# 配置
BASE_URL = "http://localhost:5000/api"
TEST_USERNAME = "admin"
TEST_PASSWORD = "admin123"

class APITestSuite:
    def __init__(self, base_url: str = BASE_URL):
        self.base_url = base_url
        self.session = requests.Session()
        self.token = None
        self.test_results = []
        
    def log_test(self, test_name: str, success: bool, message: str = "", response_data: Any = None):
        """记录测试结果"""
        result = {
            "test_name": test_name,
            "success": success,
            "message": message,
            "timestamp": datetime.now().isoformat(),
            "response_data": response_data
        }
        self.test_results.append(result)
        status = "✓" if success else "✗"
        print(f"{status} {test_name}: {message}")
        
    def make_request(self, method: str, endpoint: str, data: Dict = None, params: Dict = None) -> requests.Response:
        """发送HTTP请求"""
        url = f"{self.base_url}{endpoint}"
        headers = {"Content-Type": "application/json"}
        
        if self.token:
            headers["Authorization"] = f"Bearer {self.token}"
            
        try:
            if method.upper() == "GET":
                response = self.session.get(url, headers=headers, params=params)
            elif method.upper() == "POST":
                response = self.session.post(url, headers=headers, json=data)
            elif method.upper() == "PUT":
                response = self.session.put(url, headers=headers, json=data)
            elif method.upper() == "DELETE":
                response = self.session.delete(url, headers=headers)
            else:
                raise ValueError(f"Unsupported HTTP method: {method}")
                
            return response
        except requests.exceptions.RequestException as e:
            print(f"Request failed: {e}")
            raise
    
    def test_auth_module(self):
        """测试认证模块"""
        print("\n=== 认证模块测试 ===")
        
        # 测试登录
        login_data = {
            "username": TEST_USERNAME,
            "password": TEST_PASSWORD
        }
        
        response = self.make_request("POST", "/auth/login", login_data)
        if response.status_code == 200:
            data = response.json()
            self.token = data.get("access_token")
            self.log_test("用户登录", True, "登录成功", data.get("user"))
        else:
            self.log_test("用户登录", False, f"登录失败: {response.text}")
            return False
            
        # 测试获取用户信息
        response = self.make_request("GET", "/auth/profile")
        if response.status_code == 200:
            self.log_test("获取用户信息", True, "获取成功", response.json())
        else:
            self.log_test("获取用户信息", False, f"获取失败: {response.text}")
            
        # 测试修改密码
        change_pwd_data = {
            "old_password": TEST_PASSWORD,
            "new_password": "new_password_123"
        }
        response = self.make_request("POST", "/auth/change-password", change_pwd_data)
        if response.status_code == 200:
            self.log_test("修改密码", True, "修改成功")
            
            # 恢复原密码
            restore_pwd_data = {
                "old_password": "new_password_123",
                "new_password": TEST_PASSWORD
            }
            self.make_request("POST", "/auth/change-password", restore_pwd_data)
        else:
            self.log_test("修改密码", False, f"修改失败: {response.text}")
            
        return True
    
    def test_users_module(self):
        """测试用户管理模块"""
        print("\n=== 用户管理模块测试 ===")
        
        # 测试获取用户列表
        response = self.make_request("GET", "/users", params={"page": 1, "per_page": 10})
        if response.status_code == 200:
            data = response.json()
            self.log_test("获取用户列表", True, f"获取到 {len(data.get('users', []))} 个用户")
        else:
            self.log_test("获取用户列表", False, f"获取失败: {response.text}")
            
        # 测试创建用户
        test_user_data = {
            "username": f"test_user_{int(time.time())}",
            "email": f"test_{int(time.time())}@example.com",
            "password": "test123456",
            "name": "测试用户",
            "employee_id": f"TEST{int(time.time())}",
            "phone": "13800138000",
            "position": "测试工程师",
            "department": "测试部",
            "role": "user"
        }
        
        response = self.make_request("POST", "/users", test_user_data)
        if response.status_code == 201:
            created_user = response.json().get("user")
            user_id = created_user.get("id")
            self.log_test("创建用户", True, f"用户创建成功，ID: {user_id}")
            
            # 测试更新用户
            update_data = {
                "name": "更新后的测试用户",
                "position": "高级测试工程师"
            }
            response = self.make_request("PUT", f"/users/{user_id}", update_data)
            if response.status_code == 200:
                self.log_test("更新用户", True, "用户更新成功")
            else:
                self.log_test("更新用户", False, f"更新失败: {response.text}")
                
            # 测试删除用户
            response = self.make_request("DELETE", f"/users/{user_id}")
            if response.status_code == 200:
                self.log_test("删除用户", True, "用户删除成功")
            else:
                self.log_test("删除用户", False, f"删除失败: {response.text}")
        else:
            self.log_test("创建用户", False, f"创建失败: {response.text}")
    
    def test_groups_module(self):
        """测试组织管理模块"""
        print("\n=== 组织管理模块测试 ===")
        
        # 测试获取组织列表
        response = self.make_request("GET", "/groups")
        if response.status_code == 200:
            data = response.json()
            self.log_test("获取组织列表", True, f"获取到 {len(data.get('groups', []))} 个组织")
        else:
            self.log_test("获取组织列表", False, f"获取失败: {response.text}")
            
        # 测试创建组织
        test_group_data = {
            "name": f"测试组织_{int(time.time())}",
            "description": "这是一个测试组织"
        }
        
        response = self.make_request("POST", "/groups", test_group_data)
        if response.status_code == 201:
            created_group = response.json().get("group")
            group_id = created_group.get("id")
            self.log_test("创建组织", True, f"组织创建成功，ID: {group_id}")
            
            # 测试更新组织
            update_data = {
                "name": f"更新后的测试组织_{int(time.time())}",
                "description": "这是更新后的测试组织"
            }
            response = self.make_request("PUT", f"/groups/{group_id}", update_data)
            if response.status_code == 200:
                self.log_test("更新组织", True, "组织更新成功")
            else:
                self.log_test("更新组织", False, f"更新失败: {response.text}")
                
            # 测试删除组织
            response = self.make_request("DELETE", f"/groups/{group_id}")
            if response.status_code == 200:
                self.log_test("删除组织", True, "组织删除成功")
            else:
                self.log_test("删除组织", False, f"删除失败: {response.text}")
        else:
            self.log_test("创建组织", False, f"创建失败: {response.text}")
    
    def test_vehicles_module(self):
        """测试车辆管理模块"""
        print("\n=== 车辆管理模块测试 ===")
        
        # 测试获取车辆列表
        response = self.make_request("GET", "/vehicles")
        if response.status_code == 200:
            data = response.json()
            self.log_test("获取车辆列表", True, f"获取到 {len(data.get('vehicles', []))} 辆车")
        else:
            self.log_test("获取车辆列表", False, f"获取失败: {response.text}")
            
        # 测试创建车辆
        test_vehicle_data = {
            "license_plate": f"测试{int(time.time() % 10000)}",
            "brand": "测试品牌",
            "model": "测试型号",
            "year": 2023,
            "vehicle_type": "测试车",
            "capacity": "5人",
            "fuel_type": "汽油",
            "status": "available"
        }
        
        response = self.make_request("POST", "/vehicles", test_vehicle_data)
        if response.status_code == 201:
            created_vehicle = response.json().get("vehicle")
            vehicle_id = created_vehicle.get("id")
            self.log_test("创建车辆", True, f"车辆创建成功，ID: {vehicle_id}")
            
            # 测试更新车辆
            update_data = {
                "brand": "更新后的品牌",
                "status": "in_use"
            }
            response = self.make_request("PUT", f"/vehicles/{vehicle_id}", update_data)
            if response.status_code == 200:
                self.log_test("更新车辆", True, "车辆更新成功")
            else:
                self.log_test("更新车辆", False, f"更新失败: {response.text}")
                
            # 测试删除车辆
            response = self.make_request("DELETE", f"/vehicles/{vehicle_id}")
            if response.status_code == 200:
                self.log_test("删除车辆", True, "车辆删除成功")
            else:
                self.log_test("删除车辆", False, f"删除失败: {response.text}")
        else:
            self.log_test("创建车辆", False, f"创建失败: {response.text}")
    
    def test_materials_module(self):
        """测试物料管理模块"""
        print("\n=== 物料管理模块测试 ===")
        
        # 测试获取物料列表
        response = self.make_request("GET", "/materials")
        if response.status_code == 200:
            data = response.json()
            self.log_test("获取物料列表", True, f"获取到 {len(data.get('materials', []))} 种物料")
        else:
            self.log_test("获取物料列表", False, f"获取失败: {response.text}")
            
        # 测试获取物料分类
        response = self.make_request("GET", "/materials/categories")
        if response.status_code == 200:
            categories = response.json().get('categories', [])
            self.log_test("获取物料分类", True, f"获取到 {len(categories)} 个分类")
        else:
            self.log_test("获取物料分类", False, f"获取失败: {response.text}")
        
        # 测试创建物料
        test_material_data = {
            "name": f"测试物料_{int(time.time())}",
            "code": f"TEST{int(time.time())}",
            "category": "测试分类",
            "unit": "个",
            "specification": "测试规格说明",
            "stock_quantity": 100,
            "min_stock": 10,
            "unit_price": 25.50,
            "supplier": "测试供应商"
        }
        
        response = self.make_request("POST", "/materials", test_material_data)
        if response.status_code == 201:
            created_material = response.json().get("material")
            material_id = created_material.get("id")
            self.log_test("创建物料", True, f"物料创建成功，ID: {material_id}")
            
            # 测试更新物料
            update_data = {
                "stock_quantity": 150,
                "unit_price": 30.00
            }
            response = self.make_request("PUT", f"/materials/{material_id}", update_data)
            if response.status_code == 200:
                self.log_test("更新物料", True, "物料更新成功")
            else:
                self.log_test("更新物料", False, f"更新失败: {response.text}")
                
            # 测试库存操作
            stock_data = {
                "operation": "in",
                "quantity": 50,
                "reason": "测试入库"
            }
            response = self.make_request("POST", f"/materials/{material_id}/stock", stock_data)
            if response.status_code == 200:
                self.log_test("库存操作", True, "库存操作成功")
            else:
                self.log_test("库存操作", False, f"操作失败: {response.text}")
                
            # 测试删除物料
            response = self.make_request("DELETE", f"/materials/{material_id}")
            if response.status_code == 200:
                self.log_test("删除物料", True, "物料删除成功")
            else:
                self.log_test("删除物料", False, f"删除失败: {response.text}")
        else:
            self.log_test("创建物料", False, f"创建失败: {response.text}")
    
    def test_work_orders_module(self):
        """测试工单管理模块"""
        print("\n=== 工单管理模块测试 ===")
        
        # 测试获取工单列表
        response = self.make_request("GET", "/work_orders")
        if response.status_code == 200:
            data = response.json()
            self.log_test("获取工单列表", True, f"获取到 {len(data.get('work_orders', []))} 个工单")
        else:
            self.log_test("获取工单列表", False, f"获取失败: {response.text}")
            
        # 测试获取工单统计
        response = self.make_request("GET", "/work_orders/stats")
        if response.status_code == 200:
            self.log_test("获取工单统计", True, "统计数据获取成功", response.json())
        else:
            self.log_test("获取工单统计", False, f"获取失败: {response.text}")
            
        # 测试获取自定义字段
        response = self.make_request("GET", "/work_orders/fields")
        if response.status_code == 200:
            fields_data = response.json()
            self.log_test("获取自定义字段", True, f"获取到 {len(fields_data.get('fields', []))} 个字段")
        else:
            self.log_test("获取自定义字段", False, f"获取失败: {response.text}")
            
        # 测试创建自定义字段
        test_field_data = {
            "name": f"test_field_{int(time.time())}",
            "label": "测试字段",
            "field_type": "text",
            "is_required": False,
            "default_value": "默认值"
        }
        
        response = self.make_request("POST", "/work_orders/fields", test_field_data)
        field_id = None
        if response.status_code == 201:
            created_field = response.json().get("field")
            field_id = created_field.get("id")
            self.log_test("创建自定义字段", True, f"字段创建成功，ID: {field_id}")
        else:
            self.log_test("创建自定义字段", False, f"创建失败: {response.text}")
            
        # 测试创建工单
        test_order_data = {
            "title": f"测试工单_{int(time.time())}",
            "description": "这是一个测试工单的详细描述",
            "type": "maintenance",
            "priority": "medium",
            "location": "测试地点",
            "notes": "测试备注信息",
            "scheduled_start": "2024-01-15T09:00:00",
            "scheduled_end": "2024-01-15T17:00:00"
        }
        
        response = self.make_request("POST", "/work_orders", test_order_data)
        if response.status_code == 201:
            created_order = response.json().get("work_order")
            order_id = created_order.get("id")
            self.log_test("创建工单", True, f"工单创建成功，ID: {order_id}")
            
            # 测试获取工单详情
            response = self.make_request("GET", f"/work_orders/{order_id}")
            if response.status_code == 200:
                self.log_test("获取工单详情", True, "工单详情获取成功")
            else:
                self.log_test("获取工单详情", False, f"获取失败: {response.text}")
                
            # 测试更新工单
            update_data = {
                "status": "in_progress",
                "priority": "high",
                "notes": "更新后的备注信息"
            }
            response = self.make_request("PUT", f"/work_orders/{order_id}", update_data)
            if response.status_code == 200:
                self.log_test("更新工单", True, "工单更新成功")
            else:
                self.log_test("更新工单", False, f"更新失败: {response.text}")
                
            # 测试添加处理记录
            record_data = {
                "action": "开始处理",
                "description": "开始处理这个测试工单"
            }
            response = self.make_request("POST", f"/work_orders/{order_id}/records", record_data)
            if response.status_code == 201:
                self.log_test("添加处理记录", True, "处理记录添加成功")
            else:
                self.log_test("添加处理记录", False, f"添加失败: {response.text}")
                
            # 测试获取处理记录
            response = self.make_request("GET", f"/work_orders/{order_id}/records")
            if response.status_code == 200:
                records_data = response.json()
                self.log_test("获取处理记录", True, f"获取到 {len(records_data.get('records', []))} 条记录")
            else:
                self.log_test("获取处理记录", False, f"获取失败: {response.text}")
                
            # 测试删除工单
            response = self.make_request("DELETE", f"/work_orders/{order_id}")
            if response.status_code == 200:
                self.log_test("删除工单", True, "工单删除成功")
            else:
                self.log_test("删除工单", False, f"删除失败: {response.text}")
        else:
            self.log_test("创建工单", False, f"创建失败: {response.text}")
            
        # 清理测试字段
        if field_id:
            response = self.make_request("DELETE", f"/work_orders/fields/{field_id}")
            if response.status_code == 200:
                self.log_test("删除自定义字段", True, "字段删除成功")
            else:
                self.log_test("删除自定义字段", False, f"删除失败: {response.text}")
    
    def test_personnel_module(self):
        """测试人员管理模块"""
        print("\n=== 人员管理模块测试 ===")
        
        # 测试获取人员列表
        response = self.make_request("GET", "/personnel")
        if response.status_code == 200:
            data = response.json()
            self.log_test("获取人员列表", True, f"获取到 {len(data.get('personnel', []))} 个人员")
        else:
            self.log_test("获取人员列表", False, f"获取失败: {response.text}")
            
        # 测试创建人员
        test_person_data = {
            "name": f"测试人员_{int(time.time())}",
            "username": f"test_person_{int(time.time())}",
            "email": f"test_person_{int(time.time())}@example.com",
            "password": "Test@123456",
            "employee_id": f"EMP{int(time.time())}",
            "phone": "13800138000",
            "position": "测试工程师",
            "department": "测试部",
            "role": "user"
        }
        
        response = self.make_request("POST", "/personnel", test_person_data)
        if response.status_code == 201:
            created_person = response.json().get("personnel")
            person_id = created_person.get("id")
            self.log_test("创建人员", True, f"人员创建成功，ID: {person_id}")
            
            # 测试更新人员
            update_data = {
                "name": "更新后的测试人员",
                "position": "高级测试工程师"
            }
            response = self.make_request("PUT", f"/personnel/{person_id}", update_data)
            if response.status_code == 200:
                self.log_test("更新人员", True, "人员更新成功")
            else:
                self.log_test("更新人员", False, f"更新失败: {response.text}")
                
            # 测试删除人员
            response = self.make_request("DELETE", f"/personnel/{person_id}")
            if response.status_code == 200:
                self.log_test("删除人员", True, "人员删除成功")
            else:
                self.log_test("删除人员", False, f"删除失败: {response.text}")
        else:
            self.log_test("创建人员", False, f"创建失败: {response.text}")
    
    def run_all_tests(self):
        """运行所有测试"""
        print("开始运行API接口测试套件...")
        print(f"测试目标: {self.base_url}")
        print("=" * 50)
        
        start_time = time.time()
        
        try:
            # 认证测试必须首先运行
            if not self.test_auth_module():
                print("认证测试失败，停止后续测试")
                return
                
            # 运行其他模块测试
            self.test_users_module()
            self.test_groups_module()
            self.test_vehicles_module()
            self.test_materials_module()
            self.test_work_orders_module()
            self.test_personnel_module()
            
        except Exception as e:
            print(f"测试过程中发生错误: {e}")
            
        end_time = time.time()
        duration = end_time - start_time
        
        # 统计测试结果
        total_tests = len(self.test_results)
        passed_tests = sum(1 for result in self.test_results if result["success"])
        failed_tests = total_tests - passed_tests
        
        print("\n" + "=" * 50)
        print("测试结果汇总:")
        print(f"总测试数: {total_tests}")
        print(f"通过: {passed_tests}")
        print(f"失败: {failed_tests}")
        print(f"成功率: {(passed_tests/total_tests*100):.1f}%")
        print(f"测试耗时: {duration:.2f}秒")
        
        # 保存详细测试报告
        self.save_test_report()
        
    def save_test_report(self):
        """保存测试报告"""
        report_data = {
            "test_summary": {
                "total_tests": len(self.test_results),
                "passed_tests": sum(1 for result in self.test_results if result["success"]),
                "failed_tests": sum(1 for result in self.test_results if not result["success"]),
                "test_time": datetime.now().isoformat(),
                "base_url": self.base_url
            },
            "test_results": self.test_results
        }
        
        report_file = f"test_report_{int(time.time())}.json"
        with open(report_file, 'w', encoding='utf-8') as f:
            json.dump(report_data, f, ensure_ascii=False, indent=2)
            
        print(f"详细测试报告已保存到: {report_file}")

def main():
    """主函数"""
    print("调度系统API接口测试套件")
    print("=" * 30)
    
    # 创建测试实例
    test_suite = APITestSuite()
    
    # 运行所有测试
    test_suite.run_all_tests()

if __name__ == "__main__":
    main()